<template>
    <div>
        <el-image v-if="disabled" :src="imgSrc" :style="style" :fit="fit">
            <template #error>
                <div class="image-slot">
                    <img :src="noPicture" :style="style" />
                </div>
            </template>
        </el-image>
        <div v-else>
            <input ref="uploadInput" type="file" @click.stop accept="image/*" :multiple="false"
                @change="onFileChanged($event)" style="display: none;" />
            <div v-if="showDiv === 'plus'" :style="style" class="vimage-plus" @click="handleClickPlus">
                <el-icon :size="20">
                    <Plus />
                </el-icon>
            </div>
            <div ref="previewDiv" v-if="showDiv === 'preview'">
                <el-popover placement="bottom" trigger="hover">
                    <div class="vimag-toolset">
                        <el-button type="success" :icon="ZoomIn" circle @click="handlePictureCardPreview"></el-button>
                        <el-button type="success" :icon="Download" circle @click="handleDownload"></el-button>
                        <el-button type="success" :icon="Delete" circle @click="handleRemove"></el-button>
                    </div>
                    <template #reference>
                        <div class="vimage-preview" :style="style">
                            <img :src="previewSrc" class="vimage-preview-img" @error="() => { previewSrc = noPicture }">
                        </div>
                    </template>
                </el-popover>
            </div>
            <div v-if="showDiv === 'progress'" class="vimage-progress">
                <el-progress :percentage="percentage" :text-inside="false" type="circle" />
                <span></span>
            </div>
        </div>
    </div>
    <el-dialog v-model="dialogVisible" append-to-body width="50%">
        <div style="z-index: 1000;display: flex;align-items: center;justify-content: center;">
            <el-image :src="dialogImageUrl" :fit="fit">
                <template #error>
                    <div class="image-slot">
                        <img :src="noPicture" :style="style" />
                    </div>
                </template>
            </el-image>
        </div>
    </el-dialog>
</template>
<script setup lang="ts">
import { uploadFileStream, previewFile } from '@/api/file';
import { EpPropMergeType } from 'element-plus/es/utils/vue/props/types';
import { Delete, Download, Plus, ZoomIn } from '@element-plus/icons-vue'
import { PropType, Ref, defineProps, nextTick, onMounted, ref, unref, watch } from 'vue'
import comFunc from '@/common/comFunc';
import noPicture from '@/assets/images/noPicture.png'
import loadinggif from '@/assets/images/loading.gif'
import elHelper from '@/common/elHelper';
import { ServerConfig, Sysinfo } from '@/common/config';
import { Oss } from '@/common/aliyunOssHelper';
const props = defineProps({
    src: {
        type: String,
        default: '#'
    },
    style: {
        type: Object,
        defaul: {
            width: '100%',
            height: '100%'
        }
    },
    disabled: {
        type: Boolean,
        default: false
    },
    fit: {
        type: String as PropType<EpPropMergeType<StringConstructor, "" | "fill" | "contain" | "cover" | "none" | "scale-down", unknown> | undefined>,
        validator: (val: string) => {
            return ['', 'fill', 'contain', 'cover', 'none', 'scale-down'].includes(val)
        },
        default: 'fill'
    },
    autoUpload: {
        type: Boolean,
        default: true
    }
})
const model = defineModel({ type: String })
const uploadInput = ref()
const previewDiv = ref()
const imgSrc = ref(loadinggif)
const fit = ref(props.fit)
const dialogVisible = ref(false)
const dialogImageUrl = ref('')
const previewSrc = ref(loadinggif)
const percentage = ref(0)
const showDiv: Ref<'' | 'plus' | 'progress' | 'preview'> = ref('plus')
let file: any = null

const emit = defineEmits(['onUploaded'])

watch(() => props.src, (val) => {
    init()
    setShowState()
})
watch(() => model.value, (val) => {
    imgSrc.value = comFunc.nvl(model.value)
    init()
    setShowState()
})

const loadContent = async (src: string) => {
    if (comFunc.nvl(src) !== '') {
        if (comFunc.nvl(src).startsWith('/')) {
            imgSrc.value = loadinggif
            // let re = await previewFile(src)
            // if (re.content) {
            //     imgSrc.value = `data:image/${re.filetype};base64,${re.content}`
            // } else {
            //     imgSrc.value = noPicture
            // }
            setTimeout(() => {
                imgSrc.value = ServerConfig.REMOTE_FILE_BASE + src
                if (!props.disabled && imgSrc.value) {
                    previewSrc.value = imgSrc.value
                }
            }, 500)

        } else if (!comFunc.nvl(src).startsWith('http')) {
            imgSrc.value = noPicture
        } else {
            imgSrc.value = src
            if (!props.disabled && imgSrc.value) {
                previewSrc.value = imgSrc.value
            }
        }
    } else {
        imgSrc.value = noPicture
        if (!props.disabled) {
            previewSrc.value = noPicture
        }
    }
}
const handlePictureCardPreview = () => {
    dialogImageUrl.value = previewSrc.value
    dialogVisible.value = true
}
const handleDownload = () => {
    if (imgSrc.value.startsWith('data:')) {
        elHelper.downloadFileByBase64(imgSrc.value, file?.name)
    } else {
        elHelper.downloadFile(imgSrc.value, comFunc.getFileNameFromUrl(imgSrc.value))
    }
}
const handleRemove = () => {
    previewSrc.value = ''
    showDiv.value = 'plus'
    file = null
    uploadInput.value.value = ''
}
const handleClickPlus = () => {
    uploadInput.value.click()
}
const setShowState = () => {
    if (props.disabled) {
        showDiv.value = 'preview'
    } else {
        if (comFunc.nvl(imgSrc.value) !== '') {
            showDiv.value = 'preview'
        } else {
            showDiv.value = 'plus'
        }
    }
}
const onFileChanged = (e: any) => { // 点击上传
    const files = e.target.files
    if (files?.length && files?.length > 0) {
        file = files[0]
        const maxsize = Sysinfo.PicUploadMaxSize
        if (file.size > maxsize * 1024 * 1024) { // 限制上传图片文件大小
            elHelper.showErrorMsg(`上传大小不能超过 ${maxsize}M!`)
        } else {
            var reader = new FileReader()
            reader.readAsDataURL(file)
            reader.onload = function (result) {
                previewSrc.value = result.target?.result as string// 图片地址 Base64 格式的 可预览
            }
            if (props.autoUpload) {
                upload()
            }
            showDiv.value = 'preview'
        }
    }
}
const upload = async (): Promise<{
    isSuccess: boolean,
    msg?: string,
    path?: string,
    remotePath?: string
}> => {
    if (file) {
        percentage.value = 0
        showDiv.value = 'progress'
        // const re = await uploadFileStream(file, (per) => {
        //     percentage.value = per
        // })
        const re = await Oss.upload(file, (per) => {
            percentage.value = per
        })
        showDiv.value = 'preview'
        if (re.isSuccess) {
            emit('onUploaded', {
                path: re.path,
                remotePath: re.remotePath
            })
            return {
                isSuccess: true,
                path: comFunc.nvl(re.path),
                remotePath: comFunc.nvl(re.remotePath)
            }
        } else {
            return {
                isSuccess: false,
                msg: '上传失败'
            }
        }
    } else {
        return {
            isSuccess: true,
            path: props.src,
            remotePath: ServerConfig.REMOTE_FILE_BASE + props.src
        }
    }
}
const clear = () => {
    previewSrc.value = ''
    imgSrc.value = ''
    showDiv.value = 'plus'
    file = null
    uploadInput.value.value = ''
}
const init = async () => {
    await loadContent(props.src)
    if (!props.disabled) {
        if (props.src) {
            showDiv.value = 'preview'
        } else {
            showDiv.value = 'plus'
        }
    }
    model.value = imgSrc.value
}
onMounted(() => {
    init()
})
defineExpose({
    upload,
    clear
})
</script>
<style lang="scss" scoped>
$default-width: 160px;
$default-height: 160px;

@mixin vimage-container {
    border: 1px solid var(--border-color);
    border-radius: 5px;
    width: $default-width;
    height: $default-height;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.vimage-plus {
    @include vimage-container()
}

.vimage-preview {
    @include vimage-container()
}

.vimage-preview-img {
    width: $default-width - 10px;
    height: $default-height - 10px;
}

.vimag-toolset {
    display: flex;
    justify-content: center;
    // background-color: rgba(128, 128, 128, 0.5);
    border-radius: 5px;
}

.vimage-progress {
    padding: 2px 0 0 0;
    display: flex;
    justify-content: center;
    align-items: center;
}
</style>